/*
 * BNode.java
 * 
 * Copyright 2008 David D. Emory
 * 
 * This file is part of Five Points. See <http://www.fpdev.org> for
 * additional information regarding the project.
 * 
 * Five Points is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Five Points is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Five Points.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fpdev.core.basenet;

import org.fpdev.core.transit.Station;
import org.fpdev.apps.rtemaster.GUIOutputAcceptor;
import org.fpdev.util.FPUtil;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.fpdev.core.FPEngine;
import org.fpdev.core.Scenario;
import org.fpdev.apps.rtemaster.gui.map.MapCanvas;

public class BNode implements Serializable {

  private int id_;
  protected double x_,  y_;
  private transient Scenario scenario_;
  private short scenID_;
  private transient short onRteNet_;
  private transient boolean hasMajor_;
  private transient Station station_;

  public BNode(int id, Scenario scen, double x, double y) {
    id_ = id;
    scenario_ = scen;
    scenID_ = scenario_.getID();
    x_ = x;
    y_ = y;
    hasMajor_ = false;
    station_ = null;
  }

  public void init(FPEngine engine) {
    scenario_ = engine.getScenarios().get(scenID_);
  }

  public int getID() {
    return id_;
  }

  public Scenario getScenario() {
    return scenario_;
  }
  
  public void setScenario(Scenario s) {
    scenario_ = s;
  }

  public double getX() {
    return x_;
  }

  public double getY() {
    return y_;
  }

  public void setXY(double x, double y) {
    x_ = x;
    y_ = y;
  }

  //public void setVertex(Vertex v) { vertex_ = v; }
  //public Vertex getVertex() { return vertex_; }
  //public void killVertex() { vertex_ = null; } // for memory usage debugging purposes only
  public short getOnRteNet() {
    return onRteNet_;
  }

  public void setOnRteNet(short val) {
    onRteNet_ = val;
  }

  /*public void setRTLocator(Locator rtLoc) { //rtLoc_ = rtLoc; }
  }
  public Locator getRTLocator() { return null; // rtLoc_; }
  }*/
  public void setHasMajor(boolean hm) {
    hasMajor_ = hm;
  }

  public boolean hasMajor() {
    return hasMajor_;
  }

  public short getHasMajorCode(BaseNetwork net) {
    // 3 = excl row transit
    // 2 = major tfare
    // 1 = minor tfare
    short code = 0;
    Iterator<BLink> links = net.incidentLinks(this).iterator();
    while (links.hasNext()) {
      int linkTypeCat = links.next().getType() / 10;
      if (linkTypeCat == LinkTypes.TRANSIT) {
        code = 3;
      }
      if (linkTypeCat == LinkTypes.MAJOR_TFARE && code < 3) {
        code = 2;
      }
      if (linkTypeCat == LinkTypes.MINOR_TFARE && code < 2) {
        code = 1;
      }
    }
    return code;
  }

  public void setStation(Station station) {
    station_ = station;
  }

  public Station getStation() {
    return station_;
  }

  public void removeStation() {
    station_ = null;
  //stations_--; 
  //if(stations_<0) System.err.println("Warning: stations_ less than 0 for node #"+id_);
  }

  public boolean isStation() {
    return (station_ != null);
  }

  /*public void draw(CMapPanel panel) {
  draw(panel, false);
  }*/
  public void draw(MapCanvas canvas) {
    if (isStation()) {
      canvas.setColor(Color.black);
      canvas.drawPoint(x_, y_, 10);
      canvas.setColor(Color.white);
      canvas.drawPoint(x_, y_, 6);
    } else {
      canvas.setColor(Color.white);
      canvas.drawPoint(x_, y_, 6);
      canvas.setColor(Color.black);
      canvas.drawPoint(x_, y_, 4);
    //canvas.drawPoint(x_, y_, (this.hasMajor() ? 6 : 4));
    }
    if (canvas.getShowNodeIDs()) {
      canvas.setColor(Color.black);
      canvas.drawText("" + id_, x_, y_, 6, -3);
    }
  }

  public void drawSel(MapCanvas canvas) {
    canvas.setColor(Color.yellow);
    canvas.drawPoint(x_, y_, 20);//(isStation() ? 16 : 12));
  }

  public boolean canDelete(BaseNetwork baseNet, GUIOutputAcceptor oa) {
    Iterator<BLink> links = baseNet.incidentLinks(this).iterator();
    while (links.hasNext()) {
      BLink link = links.next();
      if (!link.canDelete(oa)) {
        oa.msg("Cannot Delete Node");
        return false;
      }
    }
    /*if(isStation()) {
    oa.msg("Cannot Delete Station Node");
    return false;			
    }*/
    return true;
  }

  public List<String> getIsectStreets(String sname, BaseNetwork net) {
    return getIsectStreets(sname, net, true);
  }

  public List<String> getIsectStreets(String sname, BaseNetwork net, boolean stripQuad) {
    sname = FPUtil.stripQuadrant(sname);
    Set s = new HashSet(); // HashtableDictionary(new ObjectHashComparator());
    List<String> list = new LinkedList<String>();
    /*if(vertex_==null) {
    System.out.println("err: null vertex at node "+id_);
    return list;			
    }*/
    Iterator<BLink> links = net.incidentLinks(this).iterator();
    //EdgeIterator edges = graph.incidentEdges(vertex_);
    while (links.hasNext()) {
      BLink link = links.next(); //(CLink) edges.nextEdge().element();
      String str = stripQuad ? FPUtil.stripQuadrant(link.getDisplayName()) : link.getDisplayName();
      if (str.length() > 0 && str.compareTo(sname) != 0) {
        if (!s.contains(str)) {
          if (link.getClassType() == BLink.CLASS_STREET && ((BLinkStreet) link).isMajor()) {
            list.add(0, str);
          } else {
            list.add(str);
          }
          s.add(str);
        }
      }
    }
    return list;
  }

  public String getIsectString(String sname, BaseNetwork net) {
    return getIsectString(sname, net, false);
  }

  public String getIsectString(String sname, BaseNetwork net, boolean shorten) {
    return getIsectString(sname, net, (shorten ? "&" : "/"), shorten);
  }

  public String getIsectString(String sname, BaseNetwork net, String separator) {
    return getIsectString(sname, net, separator, false);
  }

  public String getIsectString(String sname, BaseNetwork net, String separator, boolean shorten) {
    String toRet = "";
    Iterator<String> streets = getIsectStreets(sname, net).iterator();
    while (streets.hasNext()) {
      String str = streets.next();
      toRet += (shorten ? (str.length() > 3 ? str.substring(0, 3) : str) : str);
      if (streets.hasNext()) {
        toRet += separator;
      }
    }
    return toRet;
  }

  public String getStaNodeName() {
    if (!isStation()) {
      return "(not a station node)";
    }
    return station_.getNodeName(this);
  }

  public String getDisplayName(BaseNetwork net) {
    if (isStation()) {
      return station_.getName() + " Station";
    }
    String name = getIsectString("", net);
    if (name.length() > 0) {
      return name;
    }
    return "(" + x_ + ", " + y_ + ")";
  }

  public boolean isAddressNode() {
    return false;
  }

  public String getDisplayText() {
    return "Node " + id_ + " (" + scenario_.getName() + "): " + x_ + ", " + y_;
  }

  public Point2D.Double toPoint() {
    return new Point2D.Double(x_, y_);
  }
}































